Taglio di un ciclo for per cell Matrix

di il
11 risposte

Taglio di un ciclo for per cell Matrix

Salve a tutti
ho un ciclo for in grado di risolvere più volte un sistema OD il quale mi permette di ottenere una cell Matrix Nx7 con dimensione di ogni cella pari a Nx3. Vorrei ottenere una cell Matrix in cui la terza colonna di ogni cella abbia elementi NON più grandi di 1, vorrei quindi fermare l'iesimo ciclo non appena si ottengano valori più grandi di 1 e passare al ciclo successivo. Questa cosa è possibile farla, credo, tramite un if corredato da un break, tuttavia sto lavorando con delle cell Matrix e per quanto provi a modificare il codice, non riesce a leggermi il break. Qualcuno sa come fare?
A presto

11 Risposte

  • Re: Taglio di un ciclo for per cell Matrix

    Come pensi ti si posa aiutare a modificare il tuo codice se non lo pubblichi (compresi tutti gli input necessari per eseguirlo)?
  • Re: Taglio di un ciclo for per cell Matrix

    Nc=0.01;
    P0=2.200000e+05;
    T0=300;
    Tt0=T0;
    Pt0=P0;
    L=0.1:0.7:1;
    Mo1=[0.500000000000000,0.600000000000000,0.700000000000000];
    ChT=[0.00289672891258433,0.00279011328296122,0.00270449699691686];
    fT=[0.00438845212769167,0.00419291495433692,0.00403440372566407];

    for i=1:length(L)
    for j=1:length(Mo1)
    Y0(j)={[Tt0,Pt0,Mo1(j)]};
    ChT_cell(j)={ChT(j)};
    ft_cell(j)={fT(j)};

    Dall(i) ={[0:Nc:L(i)]};
    end
    end

    Aeffettivafinal=7.828541323557411e-07;
    Perimetro=0.011112388980385;
    for i=1:length(L)
    [~,siz(i)]=size(Dall{1,i});
    end

    for i=1:length(siz)
    for iDom = 1:numel(Dall)
    xRange = Dall{iDom};
    for iInitial = 1:numel(Y0)
    Ch=ChT_cell{iInitial};
    Fc=ft_cell{iInitial};
    [xSol{iDom,iInitial},YSol{iDom,iInitial}]=ode23(@(x,Y) ...
    tubosinglebobb(x,Y,Ch,Aeffettivafinal,Perimetro,Fc),xRange,Y0{iInitial});

    if YSol{iDom,iInitial}(1:siz(i),3)>1.00000000001
    break;
    end
    end
    end
    end
  • Re: Taglio di un ciclo for per cell Matrix

    Scusate ho dimenticato la function...eccola:
    function dYdx=tubosinglebobb(x,Y,Ch,Aeffettivafinal,Perimetro,Fc)
    gamma=1.667;
    %costante per un intervallo di T molto più grande di quello di lavoro
    Dexttantalum=0.001500000000000;
    Tw=803;%temperatura di parete (ossia quella dell'heater)
    Tt=Y(1);
    Pt=Y(2);
    M=Y(3);

    dTtdx=Ch*(Tw-Tt)*(Perimetro/Aeffettivafinal);
    dPtdx=Pt*((-gamma*((M^2)/2)*Fc*(Perimetro/Aeffettivafinal))-...
    (gamma*((M^2)/2)*dTtdx*(1/Tt)));
    dMdx=M*(((1+((gamma-1)/2)*M^2)/(1-M^2))*((gamma*(M^2)*Fc*...
    Perimetro)/(2*Aeffettivafinal))+...
    ((0.5*((gamma*M^2)+1))*(1+((gamma-1)/2)*M^2)/(1-M^2))*...
    (Ch*(Tw-Tt)*Perimetro)/(Aeffettivafinal*Tt));

    dYdx=[dTtdx;dPtdx;dMdx];
    end
  • Re: Taglio di un ciclo for per cell Matrix

    Quello che fondamentalmente vorrei ottenere è:
    non appena si dovesse raggiungere un valore >1 nella terza colonna di ogni singola cella di Ysol=> NON ottenere i valori di Ysol per la riga successiva, ma passa invece alla prossima cella (il passare alla cella successiva equivale a dire: risolvi il sistema di ODE con il successivo set di condizioni iniziali)
  • Re: Taglio di un ciclo for per cell Matrix

    Hai provato ad eseguire il codice in modalità debug?
    Non è chiaro se ti riferisci all'istruzione
    
    if YSol{iDom,iInitial}(1:siz(i),3)>1.00000000001
       break
    end
    
    Se è quella:
    [*] hai provato a settare un breakpoint alla riga che continene l'if?
    [*] hai verificato il contenuto del cellarray prima che l'istruzione "if" venga eseguita?
    [*] contiene un valore ">1"?

    Leggendo l'istruzione,

    YSol{iDom,iInitial}(1:siz(i),3)

    sembra che tu testi più di un valore contemporaneamente => (1:siz(i),3), in particolare tanti quanti "siz(i)"

    Se questo è corretto, se cioè devi testare più di un valore contemporaneamente devi modificare la definizione della condizione: supponendo di voler testare, ad esempio 5 valori:
    [*] se è sufficiente che anche uno solo soddisfi la condizione ">1" devi utilizzare la funzione any
    [*] se tutti devono soddisfare la condizione ">1" devi utilizzare la funzione all

    Se ad esempio, "x" è un vettore di 10 interi, l'istruzione x(1:5) > 1 verifica quali dei primi 5 elementi sia >1
    Il risultato è un vettore di 5 elementi di tipo logical: 1 corrisponde al fatto che l'iesimo dei 5 elementi è > 1, 0 se <=.

    Prova ad eseguire il codice che segue per vedere come l'istruzione "if" si comporta quando applicata a vettori.
    
    x=randi([1 10],1,10)
    
    if(x(1:5) > 5)
        disp([num2str(x(1:5)) ' condizione verificata'])
    else
        disp([num2str(x(1:5)) ' condizione non verificata'])
    end
    
    
    if(any(x(1:5) > 5))
        disp([num2str(x(1:5)) ' condizione verificata'])
    else
        disp([num2str(x(1:5)) ' condizione non verificata'])
    end
    
    
    if(all(x(1:5) > 5))
        disp([num2str(x(1:5)) ' condizione verificata'])
    else
        disp([num2str(x(1:5)) ' condizione non verificata'])
    end
    
  • Re: Taglio di un ciclo for per cell Matrix

    Grazie mille per la rapida risposta!!
    Si ho provato con un breakpoint (ho imposto la condizione YSol{iDom,iInitial}(6,3)>1.00000000001) ma continua a calolarmi YSol nonostante nella terza colonna in alcune righe si abbiano valori più grandi di uno. Si ho provato a verificarne il contenuto ed è proprio per questo motivo che sto cercando di escludere (o meglio, interrompere il calcolo non appena si dovessero raggiungere) i valori uguali ad uno in YSol. Si contiene valori maggiori di uno, sono questi i valori che incrementano il tempo di calcolo del codice; creano problemi se dovessero essere ottenuti prima della fine del dominio, in quanto le equazioni descrivono un problema in cui ciò non è ammesso...
    Ho provato con questa variante che mi ha suggerito
    if(all(YSol{iDom,iInitial}(1:siz(i),3)<1.00000000001))
        disp([num2str(YSol{iDom,iInitial}(1:siz(i),3)) ' condizione verificata'])
    else
        disp([num2str(YSol{iDom,iInitial}(1:siz(i),3)) ' condizione non verificata'])
        
    end
     Tuttavia ottengo
     Error using horzcat
    Dimensions of arrays being concatenated are not consistent.
    Ho provato i 3 cicli if che mi ha scritto ed effettiviamente fanno quello che vorrei; tuttavia non so se abbinati ad un odesolver, come nel mio caso, impediscano la risoluzione del sistema per M>1
  • Re: Taglio di un ciclo for per cell Matrix

    Ho provato ad eseguire il codice aggiungendo la chiamata alla finzione "any" nel blocco "if".
    Già alla prima iterazione nella colonna 3 ci sono valori > 1. i quali vengono rilevati dalla funzione "any": la condizione risulta verificata e l'istruzione "break" viene eseguita interrompendo l'esecuzione del loop più interno.
    Se vuoi che il "break" abbia effetto anche su uno dei cicli esterni, puoi settare un flag al verificarsi della condizione e testarlo nei cicli esterni.
    Se hai provato ad aggiungere la chiamata alla funzione "any" nel blocco "if" ed la condizione non risulta verificata, verifica che tutta la condizione sia inserita come input alla funzione "any".
    Se vuoi interrompere il ciclo quando tutti i valori sono > 1. devi usare la funzione "all".

    L'errore che ricevi nel codice che hai inserito nell'ultimo post, dovrebbe essere dovuto ai parametri che passi alla funzione "disp" e non all'uso della funzione "any": verifica in quale riga del codice viene generato il messaggio di errore.
  • Re: Taglio di un ciclo for per cell Matrix

    Una cosa del genere sembra funzionare
    Grazie mille per l'aiuto!!
    for iDom = 1:numel(Dall)
    xRange = Dall{iDom};
    for iInitial = 1:numel(Y0)
    Ch=ChT_cell{iInitial};
    Fc=ft_cell{iInitial};
    
    [xSol{iDom,iInitial},YSol{iDom,iInitial}]=ode23(@(x,Y) ...
    chambsinglebobb(x,Y,Ch,Aeff,Perim,Fc),xRange,Y0{iInitial});
    
    if(any(YSol{iDom,iInitial}(:,3)>1.00000000001))
       
       break
       
    end
    
    end
    
    end
  • Re: Taglio di un ciclo for per cell Matrix

    Tuttavia il tempo di calcolo è ancora eccessivo...e questa cosa penso sia dovuta al fatto che nonostante il ciclo venga bloccato, in ogni caso viene bloccato dopo che il sistema di ODE viene risolto sull'intero dominio. A questo punto credo sia necessario andare più nello specifico: vorrei che il ciclo si bloccasse non appena dovesse esser raggiunto un valore (sempre nella terza colonna di ogni cella) pari ad 1 in un certo intervallo di ogni dominio. Vorrei quindi non risolvere il sistema per l'intero dominio se dovesse spuntare fuori, ad una certa percentuale del dominio, un valore di M pari ad 1
  • Re: Taglio di un ciclo for per cell Matrix

    Per usare profile per analizzare i tempi di esecuzione delle varia parti del codice.
    Per quanto riguarda quello che chiedi (Vorrei quindi non risolvere il sistema per l'intero dominio se dovesse spuntare fuori, ad una certa percentuale del dominio, un valore di M pari ad 1[(i]) non credo di poterti aiutare.
  • Re: Taglio di un ciclo for per cell Matrix

    Va bene, grazie mille ugualmente
Devi accedere o registrarti per scrivere nel forum
11 risposte